package com.tdcy.sys.util.log;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.tdcy.framework.BaseController;
import com.tdcy.framework.BusiContext;
import com.tdcy.framework.annotation.BussinessLog;
import com.tdcy.framework.util.RequestUtils;
import com.tdcy.framework.util.StringUtils;
import com.tdcy.sys.constant.AppConstants;
import com.tdcy.sys.service.bean.LoginInfoBean;
import com.tdcy.sys.util.BusiContextExt;

@Component
@Aspect
public class LogAspect {
	private  Logger logger = null;

	public LogAspect(){
	  logger = LoggerFactory.getLogger(LogAspect.class);
	}
	
	@Pointcut("execution(* com.tdcy.biz..*.*(..))")
	public void bizCall() {}
	
	
	//类调用日志记录
	@Before("bizCall()")
	public void logBizInfo(JoinPoint  jp) {
		showlog(jp);
	}
	
	@Pointcut("execution(* com.tdcy.sys..*.*(..))")
	public void sysCall() {}
	
	//类调用日志记录
	@Before("sysCall()")
	public void logSysInfo(JoinPoint  jp) {
		showlog(jp);
	}
	
	public void showlog(JoinPoint  jp){
		Object target = jp.getTarget();
		String className = target.getClass().getName();
		if(className.startsWith("com.tdcy.framework")){
			return;
		}
		
		String methodName = jp.getSignature().getName(); // 获得方法名
		StringBuffer loginfo = new StringBuffer();
		loginfo.append("Class ：" + className+",");
		loginfo.append("Method ：" + methodName+",");
		
		if(target instanceof BaseController){
			HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
			Map<String,String> paraMap = RequestUtils.getAllParameters(request);
			Set<String> keyset = paraMap.keySet();
			List<String> parList = new ArrayList<String>();
			for(String key:keyset){
				String value = paraMap.get(key);
				parList.add(key+"="+value);
			}
			loginfo.append("Params ：" + StringUtils.join(parList,",")+"\r\n");
		}else{
			loginfo.append("\r\n");
		}
		
		logger.info(loginfo.toString());
	}
	
	 @Pointcut(value = "@annotation(com.tdcy.framework.annotation.BussinessLog)")
	    public void cutService() {
	    }

	    @Around("cutService()")
	    public Object recordSysLog(ProceedingJoinPoint point) throws Throwable {

	        //先执行业务
	        Object result = point.proceed();

	        try {
	            handle(point);
	        } catch (Exception e) {
	            logger.error("日志记录出错!", e);
	        }

	        return result;
	    }

	    private void handle(ProceedingJoinPoint point) throws Exception {
	        //获取拦截的方法名
	        Signature sig = point.getSignature();
	        MethodSignature msig = null;
	        if (!(sig instanceof MethodSignature)) {
	            throw new IllegalArgumentException("该注解只能用于方法");
	        }
	        msig = (MethodSignature) sig;
	        Object target = point.getTarget();
	        Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
	        String methodName = currentMethod.getName();

	        //如果当前用户未登录，不做日志
	        LoginInfoBean user = BusiContextExt.getLoginInfo();
	        if (null == user) {
	            return;
	        }
	        
	        String uri = (String)BusiContext.getContext(AppConstants.BUSI_REQUESTURI);

	        //获取拦截方法的参数
	        String className = point.getTarget().getClass().getName();
	        Object[] params = point.getArgs();

	        //获取操作名称
	        BussinessLog annotation = currentMethod.getAnnotation(BussinessLog.class);
	        String bussinessName = annotation.name();
	        String key = annotation.key();

	        StringBuilder sb = new StringBuilder();
	        for (Object param : params) {
	            sb.append(param);
	            sb.append(" & ");
	        }

	        String msg = annotation.remark();
	        LogManager.me().executeLog(LogTaskFactory.bussinessLog(user.getUserEO()	, bussinessName,uri, className, methodName, msg));
	    }
}